package com.ayz.gateway.center.infrastructure.nginx;

import com.ayz.gateway.center.infrastructure.nginx.Executor.GatewayServiceExpose;
import com.ayz.gateway.center.infrastructure.nginx.Executor.GatewayServiceOffline;
import com.ayz.gateway.center.infrastructure.notify.GatewayServiceChangeEvent;
import com.github.odiszapc.nginxparser.NgxConfig;
import com.github.odiszapc.nginxparser.NgxDumper;
import lombok.Getter;
import lombok.Setter;

import java.io.*;

/**
 * @ClassName AbstractGatewayServiceDeployer
 * @Description TODO: 抽象网关服务部署器
 * @Author 快乐的星球
 * @Date 2023/6/12 15:44
 * @Version 1.0
 **/
@Getter
@Setter
public abstract class AbstractGatewayServiceDeployer implements GatewayServiceDeployer{
    /**
     * Ngx配置文件的元数据信息
     */
    private NgxConfigMetadata ngxConfigMetadata;
    /**
     * NGX配置文件对象
     */
    private NgxConfig ngxConfig;

    /**
     * NGX负载均衡策略
     */
    private LoadBalanceRule loadBalanceRule;

    /**
     * 网关服务暴露器
     */
    private GatewayServiceExpose gatewayServiceExpose;
    /**
     * 网关服务下线器
     */
    private GatewayServiceOffline gatewayServiceOffline;

    private File ngxConfigInCenter;

    public AbstractGatewayServiceDeployer(NgxConfigMetadata ngxConfigMetadata) {
        this(ngxConfigMetadata,LoadBalanceRule.DEFAULT);
    }

    public AbstractGatewayServiceDeployer(NgxConfigMetadata ngxConfigMetadata, LoadBalanceRule loadBalanceRule) {
        this.ngxConfigMetadata = ngxConfigMetadata;
        this.loadBalanceRule = loadBalanceRule;

        this.gatewayServiceExpose=new GatewayServiceExpose(loadBalanceRule);
        this.gatewayServiceOffline=new GatewayServiceOffline();
    }

    public NgxConfigMetadata getNgxConfigMetadata() {
        return this.ngxConfigMetadata;
    }

    public NgxConfig getNgxConfig() {
        return this.ngxConfig;
    }

    @Override
    public NgxConfig loadNgxConfig(File ngxConfig) throws IOException {
        InputStream ips=new BufferedInputStream(new FileInputStream(ngxConfig));
        return NgxConfig.read(ips);
    }

    public void init() throws IOException{
        //TODO: 完成NgxConfig文件的装载
        String ngxConfigPath = getNgxConfigMetadata().getNgxConfigPathInCenter();
        this.ngxConfigInCenter=new File(ngxConfigPath);
        this.ngxConfig=loadNgxConfig(getNgxConfigInCenter());
    }
    public LoadBalanceRule getLoadBalanceRule() {
        return this.loadBalanceRule;
    }


    @Override
    public synchronized void deploy(GatewayServiceChangeEvent.GatewayServiceMetadata gatewayServiceMetadata) throws Exception {
        boolean isRegistry=gatewayServiceMetadata.isRegistry();
        if(getNgxConfig()==null){
            throw new IllegalStateException("GatewayServiceDeployer 必须先进行初始化执行 init()方法，才能部署服务!");
        }
        if(isRegistry){
            //网关服务上线了
            gatewayServiceExpose.exposeGatewayService(gatewayServiceMetadata.getGatewayServiceData(),getNgxConfig());
        }else {
            //网关服务下线了
            gatewayServiceOffline.offlineGatewayService(gatewayServiceMetadata.getGatewayServiceData(),getNgxConfig());
        }
        //装载配置文件
        ngxConfigDumper();
        //调用NGX应用程序重新加载配置文件
        refreshNgxConfig();
    }
    protected void ngxConfigDumper() throws IOException{
        NgxDumper dumper=new NgxDumper(getNgxConfig());
        OutputStream os=new BufferedOutputStream(new FileOutputStream(getNgxConfigInCenter()));
        dumper.dump(os);
    }
}
